#include "StdAfx.h"
//-------------------------------------------------------------------------------------------------
//ImageProcStepLibAuto.cpp  - Collection of Image Processing Functions (Steps) within a single ImageProcStep libarary        
//-------------------------------------------------------------------------------------------------
//FreeBSD License
//Copyright 2012 Will Stott All rights reserved.
//
//Redistribution and use in source and binary forms, with or without modification, are
//permitted provided that the following conditions are met:
//
//   1. Redistributions of source code must retain the above copyright notice, this list of
//      conditions and the following disclaimer.
//
//   2. Redistributions in binary form must reproduce the above copyright notice, this list
//      of conditions and the following disclaimer in the documentation and/or other materials
//      provided with the distribution.
//
//THIS SOFTWARE IS PROVIDED BY Will Stott ``AS IS'' AND ANY EXPRESS OR IMPLIED
//WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
//FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Will Stott OR
//CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
//SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
//ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
//ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//The views and conclusions contained in the software and documentation are those of the
//authors and should not be interpreted as representing official policies, either expressed
//or implied, of Will Stott.
//
//----Authors--------------------------------------------------------------------------------------
//created by: will.stott@ucl.ac.uk Feb 2012
//
//----Comments-------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
#pragma warning(disable:4995)
#include <stdio.h>
#include <Strsafe.h>

#include "TinyXmlLib.h"
#include "TinyXmlHelper.h"

#include "ImageProcSteps.h"
#include "ImageProcStepLibAuto.h"
#include "ImageProcFn.h"

#include "ImageExptLib.h"
#include "ImageExpt.h"


const char * const ImageProcStepLibAuto::attribImageDllDir = "ImageDllDir";

const char * const ImageProcStepLibAuto::BadIefPathFile = "[BadIEFPathName]";
const char * const ImageProcStepLibAuto::BadDllName = "[BadDllName]";
const char * const ImageProcStepLibAuto::BadDllPathFile = "[BadDllPathFile]";
const char * const ImageProcStepLibAuto::BadDllVersion = "[BadDLLVersion]";
const char * const ImageProcStepLibAuto::BadDllPath = "[BadDLLPath]";
const char * const ImageProcStepLibAuto::BadInfo = "[BadInfo]";

ImageProcStepLibAuto::ImageProcStepLibAuto(void) :
	_error(true),
	_pStrFilePathNameBuffer('\0'),
	_IVer(ImageProcStepLibAuto::BadDllInterface),
	_Name(ImageProcStepLibAuto::BadDllName),
	_Version(ImageProcStepLibAuto::BadDllVersion),
	_Description(ImageProcStepLibAuto::BadInfo),
	_Author(ImageProcStepLibAuto::BadInfo),
	_Copyright(ImageProcStepLibAuto::BadInfo),
	_SupportSite(ImageProcStepLibAuto::BadInfo)
{
	_pStrFilePathNameBuffer = (char *) ::malloc( (ImageExptLib::MaxPathFileNameLen+1) * sizeof(char));
}
	
ImageProcStepLibAuto::~ImageProcStepLibAuto(void)
{
	ClearAllFunctions();

	if (_pStrFilePathNameBuffer != '\0')
	{
		::free(_pStrFilePathNameBuffer);
		_pStrFilePathNameBuffer = '\0';
	}
}

bool	ImageProcStepLibAuto::Validate()
{
	bool rc = false;

	if (_pStrFilePathNameBuffer == '\0') 
		ImageExptLib::LogMsg("ImageProcStepLibAuto::Validate", "ERROR: _pStrFilePathNameBuffer is null");	
	else
	{		
		if (ValidateDetails() == true)
		{
			size_t cnt = _Procs.size();
			if (cnt > 0 ) 
			{
				rc = true;
				IImageProcFn *fn = '\0';
				for (size_t x = 0; x < cnt; x++)		
				{
					if ((fn = _Procs[x]) == '\0')
						rc = false;
					else
					{
						if (fn->IsApiValid() == false)
							ImageExptLib::LogMsg("ImageProcStepLibAuto::Validate()", "ERROR: function IsApiValid() failed - should never happen as AddFunction(ImageProcFn *proc) checks this");
						else
						{
							if (fn->GetApi()->Validate() == false )
							{
								ImageExptLib::LogMsg("ImageProcStepLibAuto::Validate()", "ERROR: function %s->Validate() failed - should never happen as AddFunction(ImageProcFn *proc) checks this", fn->GetApi()->GetFunctionName());
								rc = false;
							}
						}
					}
					if (rc == false)
						break;
				}
			}
			if (rc == true)
				_error = false;
		}
	}
	return rc;	
}


bool	ImageProcStepLibAuto::ValidateDetails()
{
	bool rc = false;

	if (_IVer == ImageProcStepLibAuto::BadDllInterface)
		ImageExptLib::LogMsg("ImageProcStepLibAuto::ValidateDetails", "ERROR: _IVer == ImageProcStepLibAuto::BadDllInterface");
	else
	{
		if((_Name.length() <= 0 ) || (_Name == ImageProcStepLibAuto::BadDllName) ) 
			ImageExptLib::LogMsg("ImageProcStepLibAuto::ValidateDetails", "ERROR: _Name is invalid");			
		else
		{
			if ((_Version.length() <= 0 ) || (_Version == ImageProcStepLibAuto::BadDllVersion))
				ImageExptLib::LogMsg("ImageProcStepLibAuto::ValidateDetails", "ERROR: _Version is invalid");
			else
			{
				if((_Description.length() <= 0 ) || (_Description == ImageProcStepLibAuto::BadInfo)) 
					ImageExptLib::LogMsg("ImageProcStepLibAuto::ValidateDetails", "ERROR: _Description is invalid");
				else
				{
					if ((_Copyright.length() <= 0 ) || (_Copyright == ImageProcStepLibAuto::BadInfo)) 
						ImageExptLib::LogMsg("ImageProcStepLibAuto::ValidateDetails", "_Copyright is invalid");						
					else
					{
						if ((_Author.length() <= 0 ) || (_Author == ImageProcStepLibAuto::BadInfo))
							ImageExptLib::LogMsg("ImageProcStepLibAuto::ValidateDetails", "_Author is invalid");	
						else
							rc = true;
					}
				}
			}
		}
	}
	return rc;
}

int		ImageProcStepLibAuto::GetFunctionCount()
{ 
	int rc = ImageProcStepLibAuto::NotFound;

	if (IsValid() == false)
		ImageExptLib::LogMsg("mageProcStepLibAuto::GetFunctionCount", "ERROR: IsValid() failed");
	else
	{
		rc = static_cast<int>(_Procs.size());
	}
	return rc;
}
bool	ImageProcStepLibAuto::SaveLibFunctionDefsToXml(const wchar_t *PathFileNameXml, const wchar_t *ImageProcStepLibDirwStr)
{
	bool rc = false;

	TiXmlDocument xmlDoc;

	if (PathFileNameXml == '\0')
		ImageExptLib::LogMsg("ImageProcStepLibAuto::SaveLibFunctionDefsToXml()", "ERROR: PathFileNameXml is null");	
	else
	{
		if ( IsValid() == false )
			ImageExptLib::LogMsg("ImageProcStepLibAuto::SaveLibFunctionDefsToXml()", "ERROR: library is empty or has not been validated" );	
		else
		{
			const char *pathfilenamexml = ImageExptLib::ConvertwStrToStr(_pStrFilePathNameBuffer, ImageExptLib::MaxPathFileNameLen, PathFileNameXml, ImageExptLib::MaxPathFileNameLen);
			if ( pathfilenamexml == '\0' )
				ImageExptLib::LogMsg("ImageProcStepLibAuto::SaveLibFunctionDefsToXml()", "ERROR: failed to convert PathFileNameIefwStr" );	
			else
			{
				std::string pathfilename(pathfilenamexml);
				if (xmlDoc.LoadFile(pathfilename.c_str()) == false)
					ImageExptLib::LogMsg("ImageProcStepLibAuto::SaveLibFunctionDefsToXml()", "ERROR: failed to open %s", pathfilename.c_str() );	
				else
				{
					TiXmlElement * header = TinyXmlHelper::GetHeaderElement(&xmlDoc);
					if (header == '\0')
						ImageExptLib::LogMsg("ImageProcStepLibAuto::SaveLibFunctionDefsToXml()", "ERROR: header not found in IEF");	
					else
					{
						TiXmlElement * steps = TinyXmlHelper::FindChildXmlElement(header, ImageProcSteps::xmlProcSteps );
						if (steps == '\0')
							ImageExptLib::LogMsg("ImageProcStepLibAuto::SaveLibFunctionDefsToXml()", "ERROR: <%s> not found in header of IEF", ImageProcSteps::xmlProcSteps);
						else
						{
							steps->Clear();
							const char *pathdll = ImageExptLib::ConvertwStrToStr(_pStrFilePathNameBuffer, ImageExptLib::MaxPathFileNameLen, ImageProcStepLibDirwStr, ImageExptLib::MaxPathNameLen);
							if ( pathdll == '\0' )
								ImageExptLib::LogMsg("ImageProcStepLibAuto::SaveLibFunctionDefsToXml()", "ERROR: failed to convert ImageProcStepLibDirwStr" );	
							else
							{
								std::string PathDirDLL(pathdll);
								steps->SetAttribute(ImageProcStepLibAuto::attribImageDllDir, PathDirDLL.c_str()); 

								int apiCnt = GetFunctionCount();
								if ( apiCnt == ImageProcStepLibAuto::NotFound )
									ImageExptLib::LogMsg("ImageProcStepLibAuto::SaveLibFunctionDefsToXml()", "ERROR: no functions found in library");
								else
								{	
									int x = 0;
									for (x = 0; x < apiCnt; x++ )
									{
										TiXmlElement *step = TinyXmlLib::CreateSection (steps, ImageProcStep::xmlProcStep, "(give description of step here)" );
										if (step == '\0')
											break;
										else
										{
											step->SetAttribute(ImageProcStep::attribStepNum, x);
											step->SetAttribute(ImageProcStep::attribLibName,  GetName() );
											step->SetAttribute(ImageProcStep::attribLibVersion,  GetVersion());
											step->SetAttribute(ImageProcStep::attribInterfaceVersion, GetIVersion());
											if (GetFunction(x)->GetApi()->SaveFunctionDefToXml(step) == false)
												break;
										}
									}
									if ( x != apiCnt )
										ImageExptLib::LogMsg("ImageProcStepLibAuto::SaveLibFunctionDefsToXml()", "ERROR: failed to create %s in Xml file: problem at step %d of %d", ImageProcSteps::xmlProcSteps, x, apiCnt);
									else
										rc = true;
								}
							}
						}
					}
					if ( rc == true )
						xmlDoc.SaveFile();
				}
			}
		}
	}
	return rc;
}


bool	ImageProcStepLibAuto::AddFunction(IImageProcFn *proc)
{
	bool rc = false;

	if (proc == '\0') 
		ImageExptLib::LogMsg("ImageProcStepLibAuto::AddFunction", "ERROR: proc is null");	
	else
	{
		if (proc->IsApiValid() == false)		
			ImageExptLib::LogMsg("ImageProcStepLibAuto::AddFunction", "ERROR: proc->IsValid() failed");	
		else
		{
			if ( GetFnPosition(proc->GetApi()->GetFunctionName()) != ImageProcStepLibAuto::NotFound)
				ImageExptLib::LogMsg("ImageProcStepLibAuto::AddFunction", "ERROR: Function (%s) is already in this library", proc->GetApi()->GetFunctionName());	
			else
			{
				//set _error = true; //not necessary as effectively all Validate() does is to invoke proc->IsApiValid() which has been done above
				//					 //when we check the collection of functions, we just check that each one is valid (not like when we check
				//					 //a collection of parameters to make sure there is alaways a Result param, no missing indexes, etc) 
				_Procs.push_back(proc);
				rc = true;
			}
		}
	}
	return rc;
}

IImageProcFn *ImageProcStepLibAuto::GetFunction(int position)
{ 
	IImageProcFn *rc = '\0';

	if (IsValid() == false)
		ImageExptLib::LogMsg("mageProcStepLibAuto::GetFunction(position)", "ERROR: IsValid() failed");
	else
	{		
		int cnt = static_cast<int>(_Procs.size());
		if ((position > (cnt-1)) || (position < 0)) 
			ImageExptLib::LogMsg("mageProcStepLibAuto::GetFunction(position)", "ERROR: position %d is invalid (LibCnt=%d)", position, cnt);
		else
			rc = _Procs[position];
	}
	return rc;
}

IImageProcFn *	ImageProcStepLibAuto::GetFunction(const char *FnName)
{
	IImageProcFn *rc = '\0';

	if (IsValid() == false)
		ImageExptLib::LogMsg("mageProcStepLibAuto::GetFunction(name)", "ERROR: IsValid() failed");
	else
	{	
		int pos = ImageProcStepLibAuto::NotFound;
		if ( (pos = GetFnPosition(FnName)) == ImageProcStepLibAuto::NotFound)
			ImageExptLib::LogMsg("mageProcStepLibAuto::GetFunction(name)", "ERROR: Function %s not found", (FnName != '\0') ? FnName : "(null)");
		else
			rc = _Procs[pos];
	}
	return rc;
}

bool ImageProcStepLibAuto::ClearAllFunctions()
{
	bool rc = false;

	size_t cnt = _Procs.size();
	if (cnt > 0 )
	{
		for (size_t x = 0; x < cnt; x++)
			delete  _Procs[x];
		_Procs.clear();
		rc = true;
	}
	_error = true;
	return rc;
}

//-------------------------------------------------------------------------------------------------
//			PRIVATE
//-------------------------------------------------------------------------------------------------

int	ImageProcStepLibAuto::GetFnPosition(const char *FunctionName)
{
	int rc = ImageProcStepLibAuto::NotFound;

	if (FunctionName != '\0')
	{
		std::string fnname(FunctionName);
		size_t cnt = _Procs.size();
		if (cnt > 0 )
		{
			for (size_t x = 0; x < cnt; x++)
			{
				if (fnname == _Procs[x]->GetApi()->GetFunctionName())	//GetApi should never fail as IsApiValid() ensures GetApi() returns a valid pointer to a good ProcDef
				{
					rc = x;
					break;
				}
			}
		}
	}
	return rc;
}


#pragma warning(default:4995)
//-------------------------------------------------------------------------------------------------
//			E N D   O F   F I L E
//-------------------------------------------------------------------------------------------------
